/* SPDX-License-Identifier: Apache-2.0 */

#ifndef __MACROS_H
#define __MACROS_H

// Internal helpers to concatenate two tokens. Do not use directly
#define __CONCAT_IMPL(x, y) x##y
#define __CONCAT(x, y) __CONCAT_IMPL(x, y)

// Internal helpers to count the number of arguments. Do not use directly
#define __VA_NARGS_IMPL(_1, _2, _3, _4, N, ...) N
#define __VA_NARGS(...) __VA_NARGS_IMPL(__VA_ARGS__, 4, 3, 2, 1)

// Internal helpers to expand the snapshotter's programs. Do not use directly
#define __GADGET_ITER_PROGRAMS_EXPAND_1(name, type, programName1)    \
	const void *gadget_iter_##name##___##type##___##programName1 \
		__attribute__((unused));
#define __GADGET_ITER_PROGRAMS_EXPAND_2(name, type, programName1,                   \
					programName2)                               \
	const void *                                                                \
		gadget_iter_##name##___##type##___##programName1##___##programName2 \
		__attribute__((unused));
#define __GADGET_ITER_PROGRAMS_EXPAND_3(name, type, programName1,                                      \
					programName2, programName3)                                    \
	const void *                                                                                   \
		gadget_iter_##name##___##type##___##programName1##___##programName2##___##programName3 \
		__attribute__((unused));
#define __GADGET_ITER_PROGRAMS_EXPAND(name, type, nargs, ...) \
	__CONCAT(__GADGET_ITER_PROGRAMS_EXPAND_, nargs)       \
	(name, type, __VA_ARGS__)
#define __GADGET_ITER_IMPL(name, type, ...)                                \
	__GADGET_ITER_PROGRAMS_EXPAND(name, type, __VA_NARGS(__VA_ARGS__), \
				      __VA_ARGS__)

// Public macros. Use these in your code
// Keep this aligned with pkg/gadgets/run/types/metadata.go

// GADGET_TRACER is used to define a tracer. Currently only one tracer per eBPF object is allowed.
// name is the tracer's name
// map_name is the name of the perf event array or ring buffer maps used to send events to user
// space
// event_type is the name of the structure that describes the event
#define GADGET_TRACER(name, map_name, event_type)                        \
	const void *gadget_tracer_##name##___##map_name##___##event_type \
		__attribute__((unused));                                 \
	const struct event_type *__gadget_tracer_type_##name             \
		__attribute__((unused));

// GADGET_PARAM is used to indicate that a given variable is used as a parameter.
// Users of Inspektor Gadget can set these values from userspace
#define GADGET_PARAM(name) \
	const void *gadget_param_##name __attribute__((unused));

// GADGET_SNAPSHOTTER is used to define a snapshotter:
// name is the snapshotter's name
// type is the name of the structure that describes each element in a snapshot
// ... is the variadic list of programs (min 1, max 3) that generate a snapshot
// The snapshotter's output will be the union of the snapshots generated by the programs
// Deprecated: please use GADGET_ITER() instead
#define GADGET_SNAPSHOTTER(name, type, ...)              \
	const struct type *unusedevent_##name##___##type \
		__attribute__((unused));                 \
	__GADGET_ITER_IMPL(name, type, __VA_ARGS__)

// GADGET_ITER is used to define an iterator:
// name is the iterator's name
// type is the name of the structure that describes each element in an iterator
// ... is the variadic list of programs (min 1, max 3) that generate an iterator
// The iterator's output will be the union of the entries returned by the individual iter programs
#define GADGET_ITER(name, type, ...)                     \
	const struct type *unusedevent_##name##___##type \
		__attribute__((unused));                 \
	__GADGET_ITER_IMPL(name, type, __VA_ARGS__)

// GADGET_MAPITER defines maps that IG should periodically fetch into data sources
// - name is the name of the map iterator
// - mapname is the name of the hash map used to send events to user space.
#define GADGET_MAPITER(name, mapname) \
	const void *gadget_mapiter_##name##___##mapname __attribute__((unused));

#endif /* __MACROS_H */
